]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
main: Remove transitions from child adjustments
authorFlorian Müllner <fmuellner@gnome.org>
Mon, 11 Sep 2023 12:00:24 +0000 (14:00 +0200)
committerFlorian Müllner <fmuellner@gnome.org>
Thu, 14 Sep 2023 14:46:31 +0000 (16:46 +0200)
When commit 4d963c432b introduced the global workspace adjustment,
it mostly copied the adjustment handling from the overview that it
set out to replace.

That includes cancelling ongoing transitions when the number of
workspaces changed. However that missed that transitions don't
happen on the main adjustment, but on the "child" adjustments
returned from `createWorkspacesAdjustment()`.

Address this by tracking all child adjustments, and cancel transitions
there as well when necessary. Use weak refs to not
interfere with garbage collection, in case an extension creates
its own child adjustment.

Fixes: 4d963c432b ("main: Introduce global workspaces adjustment")
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7000
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2949>

js/ui/main.js

index 6240b12fea2aaf21da095fd9f6c3d4486f55da10..9e14bc141dab892f2b16e8215c68c07eb13cd111 100644 (file)
@@ -98,6 +98,7 @@ let _themeResource = null;
 let _oskResource = null;
 let _iconResource = null;
 let _workspacesAdjustment = null;
+let _workspaceAdjustmentRegistry = null;
 
 Gio._promisify(Gio.File.prototype, 'delete_async');
 Gio._promisify(Gio.File.prototype, 'touch_async');
@@ -445,6 +446,30 @@ function _loadDefaultStylesheet() {
     loadTheme();
 }
 
+class AdjustmentRegistry {
+    #count = 0;
+    #adjustments = new Map();
+    #registry = new FinalizationRegistry(key => {
+        this.#adjustments.delete(key);
+    });
+
+    register(adj) {
+        const key = this.#count++;
+        this.#adjustments.set(key, new WeakRef(adj));
+        this.#registry.register(adj, key);
+    }
+
+    forEach(callback) {
+        this.#adjustments.forEach((ref, key) => {
+            const adj = ref.deref();
+            if (adj)
+                callback(adj);
+            else
+                this.#adjustments.delete(key);
+        });
+    }
+}
+
 function _loadWorkspacesAdjustment() {
     const {workspaceManager} = global;
     const activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
@@ -467,9 +492,12 @@ function _loadWorkspacesAdjustment() {
 
         // A workspace might have been inserted or removed before the active
         // one, causing the adjustment to go out of sync, so update the value
+        _workspaceAdjustmentRegistry.forEach(c => c.remove_transition('value'));
         _workspacesAdjustment.remove_transition('value');
         _workspacesAdjustment.value = newActiveIndex;
     });
+
+    _workspaceAdjustmentRegistry = new AdjustmentRegistry();
 }
 
 /**
@@ -498,6 +526,8 @@ export function createWorkspacesAdjustment(actor) {
     for (const [propName, flags] of properties)
         _workspacesAdjustment.bind_property(propName, adjustment, propName, flags);
 
+    _workspaceAdjustmentRegistry.register(adjustment);
+
     return adjustment;
 }